<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>3.5. LDAP Authentication</title>
<link rel="stylesheet" href="dbstyle.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
<link rel="start" href="index.html" title="Programmer's Reference Guide">
<link rel="up" href="zend.auth.html" title="Chapter 3. Zend_Auth">
<link rel="prev" href="zend.auth.adapter.http.html" title="3.4. HTTP Authentication Adapter">
<link rel="next" href="zend.auth.adapter.openid.html" title="3.6. Open ID Authentication">
<link rel="chapter" href="introduction.html" title="Chapter 1. Introduction to Zend Framework">
<link rel="chapter" href="zend.acl.html" title="Chapter 2. Zend_Acl">
<link rel="chapter" href="zend.auth.html" title="Chapter 3. Zend_Auth">
<link rel="chapter" href="zend.cache.html" title="Chapter 4. Zend_Cache">
<link rel="chapter" href="zend.config.html" title="Chapter 5. Zend_Config">
<link rel="chapter" href="zend.console.getopt.html" title="Chapter 6. Zend_Console_Getopt">
<link rel="chapter" href="zend.controller.html" title="Chapter 7. Zend_Controller">
<link rel="chapter" href="zend.currency.html" title="Chapter 8. Zend_Currency">
<link rel="chapter" href="zend.date.html" title="Chapter 9. Zend_Date">
<link rel="chapter" href="zend.db.html" title="Chapter 10. Zend_Db">
<link rel="chapter" href="zend.debug.html" title="Chapter 11. Zend_Debug">
<link rel="chapter" href="zend.dojo.html" title="Chapter 12. Zend_Dojo">
<link rel="chapter" href="zend.dom.html" title="Chapter 13. Zend_Dom">
<link rel="chapter" href="zend.exception.html" title="Chapter 14. Zend_Exception">
<link rel="chapter" href="zend.feed.html" title="Chapter 15. Zend_Feed">
<link rel="chapter" href="zend.filter.html" title="Chapter 16. Zend_Filter">
<link rel="chapter" href="zend.form.html" title="Chapter 17. Zend_Form">
<link rel="chapter" href="zend.gdata.html" title="Chapter 18. Zend_Gdata">
<link rel="chapter" href="zend.http.html" title="Chapter 19. Zend_Http">
<link rel="chapter" href="zend.infocard.html" title="Chapter 20. Zend_InfoCard">
<link rel="chapter" href="zend.json.html" title="Chapter 21. Zend_Json">
<link rel="chapter" href="zend.layout.html" title="Chapter 22. Zend_Layout">
<link rel="chapter" href="zend.ldap.html" title="Chapter 23. Zend_Ldap">
<link rel="chapter" href="zend.loader.html" title="Chapter 24. Zend_Loader">
<link rel="chapter" href="zend.locale.html" title="Chapter 25. Zend_Locale">
<link rel="chapter" href="zend.log.html" title="Chapter 26. Zend_Log">
<link rel="chapter" href="zend.mail.html" title="Chapter 27. Zend_Mail">
<link rel="chapter" href="zend.measure.html" title="Chapter 28. Zend_Measure">
<link rel="chapter" href="zend.memory.html" title="Chapter 29. Zend_Memory">
<link rel="chapter" href="zend.mime.html" title="Chapter 30. Zend_Mime">
<link rel="chapter" href="zend.openid.html" title="Chapter 31. Zend_OpenId">
<link rel="chapter" href="zend.paginator.html" title="Chapter 32. Zend_Paginator">
<link rel="chapter" href="zend.pdf.html" title="Chapter 33. Zend_Pdf">
<link rel="chapter" href="zend.registry.html" title="Chapter 34. Zend_Registry">
<link rel="chapter" href="zend.rest.html" title="Chapter 35. Zend_Rest">
<link rel="chapter" href="zend.search.lucene.html" title="Chapter 36. Zend_Search_Lucene">
<link rel="chapter" href="zend.server.html" title="Chapter 37. Zend_Server">
<link rel="chapter" href="zend.service.html" title="Chapter 38. Zend_Service">
<link rel="chapter" href="zend.session.html" title="Chapter 39. Zend_Session">
<link rel="chapter" href="zend.soap.html" title="Chapter 40. Zend_Soap">
<link rel="chapter" href="zend.test.html" title="Chapter 41. Zend_Test">
<link rel="chapter" href="zend.text.html" title="Chapter 42. Zend_Text">
<link rel="chapter" href="zend.timesync.html" title="Chapter 43. Zend_TimeSync">
<link rel="chapter" href="zend.translate.html" title="Chapter 44. Zend_Translate">
<link rel="chapter" href="zend.uri.html" title="Chapter 45. Zend_Uri">
<link rel="chapter" href="zend.validate.html" title="Chapter 46. Zend_Validate">
<link rel="chapter" href="zend.version.html" title="Chapter 47. Zend_Version">
<link rel="chapter" href="zend.view.html" title="Chapter 48. Zend_View">
<link rel="chapter" href="zend.xmlrpc.html" title="Chapter 49. Zend_XmlRpc">
<link rel="appendix" href="requirements.html" title="Appendix A. Zend Framework Requirements">
<link rel="appendix" href="coding-standard.html" title="Appendix B. Zend Framework Coding Standard for PHP">
<link rel="appendix" href="copyrights.html" title="Appendix C. Copyright Information">
<link rel="index" href="the.index.html" title="Index">
<link rel="subsection" href="zend.auth.adapter.ldap.html#zend.auth.adapter.ldap.introduction" title="3.5.1. Introduction">
<link rel="subsection" href="zend.auth.adapter.ldap.html#zend.auth.adapter.ldap.usage" title="3.5.2. Usage">
<link rel="subsection" href="zend.auth.adapter.ldap.html#zend.auth.adapter.ldap.api" title="3.5.3. The API">
<link rel="subsection" href="zend.auth.adapter.ldap.html#zend.auth.adapter.ldap.server-options" title="3.5.4. Server Options">
<link rel="subsection" href="zend.auth.adapter.ldap.html#zend.auth.adapter.ldap.debugging" title="3.5.5. Collecting Debugging Messages">
<link rel="subsection" href="zend.auth.adapter.ldap.html#zend.auth.adapter.ldap.options-common-server-specific" title="3.5.6. Common Options for Specific Servers">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<div class="navheader"><table width="100%" summary="Navigation header">
<tr><th colspan="3" align="center">3.5. LDAP Authentication</th></tr>
<tr>
<td width="20%" align="left">
<a accesskey="p" href="zend.auth.adapter.http.html">Prev</a> </td>
<th width="60%" align="center">Chapter 3. Zend_Auth</th>
<td width="20%" align="right"> <a accesskey="n" href="zend.auth.adapter.openid.html">Next</a>
</td>
</tr>
</table></div>
<div class="sect1" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="zend.auth.adapter.ldap"></a>3.5. LDAP Authentication</h2></div></div></div>
<div class="sect2" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="zend.auth.adapter.ldap.introduction"></a>3.5.1. Introduction</h3></div></div></div>
<p>
            <code class="code">Zend_Auth_Adapter_Ldap</code> supports web application authentication with LDAP services. Its
            features include username and domain name canonicalization, multi-domain authentication, and failover
            capabilities. It has been tested to work with
            <a href="http://www.microsoft.com/windowsserver2003/technologies/directory/activedirectory/" target="_top">Microsoft
            Active Directory</a> and <a href="http://www.openldap.org/" target="_top">OpenLDAP</a>, but it should also
            work with other LDAP service providers.
        </p>
<p>
            This documentation includes a guide on using <code class="code">Zend_Auth_Adapter_Ldap</code>, an exploration of its
            API, an outline of the various available options, diagnostic information for troubleshooting authentication
            problems, and example options for both Active Directory and OpenLDAP servers.
        </p>
</div>
<div class="sect2" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="zend.auth.adapter.ldap.usage"></a>3.5.2. Usage</h3></div></div></div>
<p>
            To incorporate <code class="code">Zend_Auth_Adapter_Ldap</code> authentication into your application quickly, even if
            you're not using <code class="code">Zend_Controller</code>, the meat of your code should look something like the
            following:
            </p>
<pre class="programlisting">&lt;?php
$username = $this-&gt;_request-&gt;getParam('username');
$password = $this-&gt;_request-&gt;getParam('password');

$auth = Zend_Auth::getInstance();

require_once 'Zend/Config/Ini.php';
$config = new Zend_Config_Ini('../application/config/config.ini', 'production');
$log_path = $config-&gt;ldap-&gt;log_path;
$options = $config-&gt;ldap-&gt;toArray();
unset($options['log_path']);

require_once 'Zend/Auth/Adapter/Ldap.php';
$adapter = new Zend_Auth_Adapter_Ldap($options, $username, $password);

$result = $auth-&gt;authenticate($adapter);

if ($log_path) {
    $messages = $result-&gt;getMessages();

    require_once 'Zend/Log.php';
    require_once 'Zend/Log/Writer/Stream.php';
    require_once 'Zend/Log/Filter/Priority.php';
    $logger = new Zend_Log();
    $logger-&gt;addWriter(new Zend_Log_Writer_Stream($log_path));
    $filter = new Zend_Log_Filter_Priority(Zend_Log::DEBUG);
    $logger-&gt;addFilter($filter);

    foreach ($messages as $i =&gt; $message) {
        if ($i-- &gt; 1) { // $messages[2] and up are log messages
            $message = str_replace("\n", "\n  ", $message);
            $logger-&gt;log("Ldap: $i: $message", Zend_Log::DEBUG);
        }
    }
}</pre>
<p>
            Of course the logging code is optional, but it is highly recommended that you use a logger.
            <code class="code">Zend_Auth_Adapter_Ldap</code> will record just about every bit of information anyone could want in
            <code class="code">$messages</code> (more below), which is a nice feature in itself for something that has a history of
            being notoriously difficult to debug.
        </p>
<p>
            The <code class="code">Zend_Config_Ini</code> code is used above to load the adapter options. It is also optional. A
            regular array would work equally well. The following is an example
            <code class="code">application/config/config.ini</code> file that has options for two separate servers. With multiple
            sets of server options the adapter will try each in order until the credentials are successfully
            authenticated. The names of the servers (e.g., <code class="code">server1</code> and <code class="code">server2</code>) are largely
            arbitrary. For details regarding the options array, see the <span class="emphasis"><em>Server Options</em></span> section
            below. Note that <code class="code">Zend_Config_Ini</code> requires that any values with equals characters
            (<code class="code">=</code>) will need to be quoted (like the DNs shown below).
            </p>
<pre class="programlisting">[production]

ldap.log_path = /tmp/ldap.log

; Typical options for OpenLDAP
ldap.server1.host = s0.foo.net
ldap.server1.accountDomainName = foo.net
ldap.server1.accountDomainNameShort = FOO
ldap.server1.accountCanonicalForm = 3
ldap.server1.username = "CN=user1,DC=foo,DC=net"
ldap.server1.password = pass1
ldap.server1.baseDn = "OU=Sales,DC=foo,DC=net"
ldap.server1.bindRequiresDn = true

; Typical options for Active Directory
ldap.server2.host = dc1.w.net
ldap.server2.useSsl = true
ldap.server2.accountDomainName = w.net
ldap.server2.accountDomainNameShort = W
ldap.server2.accountCanonicalForm = 3
ldap.server2.baseDn = "CN=Users,DC=w,DC=net"</pre>
<p>
            The above configuration will instruct <code class="code">Zend_Auth_Adapter_Ldap</code> to attempt to authenticate users
            with the OpenLDAP server <code class="code">s0.foo.net</code> first. If the authentication fails for any reason, the AD
            server <code class="code">dc1.w.net</code> will be tried.
        </p>
<p>
            With servers in different domains, this configuration illustrates multi-domain authentication. You can also
            have multiple servers in the same domain to provide redundancy.
        </p>
<p>
            Note that in this case, even though OpenLDAP has no need for the short NetBIOS style domain name used by
            Windows we provide it here for name canonicalization purposes (described in the
            <span class="emphasis"><em>Username Canonicalization</em></span> section below).
        </p>
</div>
<div class="sect2" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="zend.auth.adapter.ldap.api"></a>3.5.3. The API</h3></div></div></div>
<p>
            The <code class="code">Zend_Auth_Adapter_Ldap</code> constructor accepts three parameters.
        </p>
<p>
            The <code class="code">$options</code> parameter is required and must be an array containing one or more sets of
            options. Note that it is <span class="emphasis"><em>an array of arrays</em></span> of
            <a href="zend.ldap.html" title="Chapter 23. Zend_Ldap">Zend_Ldap</a> options. Even if you will be using only one LDAP server, the
            options must still be within another array.
        </p>
<p>
            Below is <a href="http://php.net/print_r" target="_top"><code class="code">print_r()</code></a> output of an example options
            parameter containing two sets of server options for LDAP servers <code class="code">s0.foo.net</code> and
            <code class="code">dc1.w.net</code> (same options as the above INI representation):
            </p>
<pre class="programlisting">Array
(
    [server2] =&gt; Array
        (
            [host] =&gt; dc1.w.net
            [useSsl] =&gt; 1
            [accountDomainName] =&gt; w.net
            [accountDomainNameShort] =&gt; W
            [accountCanonicalForm] =&gt; 3
            [baseDn] =&gt; CN=Users,DC=w,DC=net
        )

    [server1] =&gt; Array
        (
            [host] =&gt; s0.foo.net
            [accountDomainName] =&gt; foo.net
            [accountDomainNameShort] =&gt; FOO
            [accountCanonicalForm] =&gt; 3
            [username] =&gt; CN=user1,DC=foo,DC=net
            [password] =&gt; pass1
            [baseDn] =&gt; OU=Sales,DC=foo,DC=net
            [bindRequiresDn] =&gt; 1
        )

)</pre>
<p>
            The information provided in each set of options above is different mainly because AD does not require a
            username be in DN form when binding (see the <code class="code">bindRequiresDn</code> option in the
            <span class="emphasis"><em>Server Options</em></span> section below), which means we can omit the a number of options
            associated with retrieving the DN for a username being authenticated.
        </p>
<div class="note"><table border="0" summary="Note: What is a DN?">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td>
<th align="left">What is a DN?</th>
</tr>
<tr><td align="left" valign="top"><p>
                A DN or "distinguished name" is a string that represents the path to an object within the LDAP
                directory. Each comma separated component is an attribute and value representing a node. The components
                are evaluated in reverse. For example, the user account
                <span class="emphasis"><em>CN=Bob Carter,CN=Users,DC=w,DC=net</em></span> is located directly within the
                <span class="emphasis"><em>CN=Users,DC=w,DC=net container</em></span>. This structure is best explored with an LDAP
                browser like the ADSI Edit MMC snap-in for Active Directory or phpLDAPadmin.
            </p></td></tr>
</table></div>
<p>
            The names of servers (e.g. '<code class="code">server1</code>' and '<code class="code">server2</code>' shown above) are largely
            arbitrary, but for the sake of using <code class="code">Zend_Config</code>, the identifiers should be present (as
            opposed to being numeric indexes) and should not contain any special characters used by the associated file
            formats (e.g. the '<code class="code">.</code>' INI property separator, '<code class="code">&amp;</code>' for XML entity references,
            etc).
        </p>
<p>
            With multiple sets of server options, the adapter can authenticate users in multiple domains and provide
            failover so that if one server is not available, another will be queried.
        </p>
<div class="note"><table border="0" summary="Note: The Gory Details - What exactly happens in the authenticate method?">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td>
<th align="left">The Gory Details - What exactly happens in the authenticate method?</th>
</tr>
<tr><td align="left" valign="top"><p>
                When the <code class="code">authenticate()</code> method is called, the adapter iterates over each set of server
                options, sets them on the internal <code class="code">Zend_Ldap</code> instance and calls the
                <code class="code">Zend_Ldap::bind()</code> method with the username and password being authenticated. The
                <code class="code">Zend_Ldap</code> class checks to see if the username is qualified with a domain (e.g., has a
                domain component like <span class="emphasis"><em>alice@foo.net</em></span> or <span class="emphasis"><em>FOO\alice</em></span>). If a
                domain is present, but it does not match either of the server's domain names
                (<span class="emphasis"><em>foo.net</em></span> or <span class="emphasis"><em>FOO</em></span>), a special exception is thrown and caught by
                <code class="code">Zend_Auth_Adapter_Ldap</code> that causes that server to be ignored and the next set of server
                options is selected. If a domain <span class="emphasis"><em>does</em></span> match, or if the user did not supply a
                qualified username, <code class="code">Zend_Ldap</code> proceeds to try to bind with the supplied credentials. If
                the bind is not successful, <code class="code">Zend_Ldap</code> throws a <code class="code">Zend_Ldap_Exception</code> which is
                caught by <code class="code">Zend_Auth_Adapter_Ldap</code> and the next set of server options is tried. If the bind
                is successful, the iteration stops, and the adapter's <code class="code">authenticate()</code> method returns a
                successful result. If all server options have been tried without success, the authentication fails, and
                <code class="code">authenticate()</code> returns a failure result with error messages from the last iteration.
            </p></td></tr>
</table></div>
<p>
            The username and password parameters of the <code class="code">Zend_Auth_Adapter_Ldap</code> constructor represent the
            credentials being authenticated (i.e., the credentials supplied by the user through your HTML login form).
            Alternatively, they may also be set with the <code class="code">setUsername()</code> and <code class="code">setPassword()</code>
            methods.
        </p>
</div>
<div class="sect2" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="zend.auth.adapter.ldap.server-options"></a>3.5.4. Server Options</h3></div></div></div>
<p>
            Each set of server options <span class="emphasis"><em>in the context of Zend_Auth_Adapter_Ldap</em></span> consists of the
            following options, which are passed, largely unmodified, to <code class="code">Zend_Ldap::setOptions()</code>:

            </p>
<div class="table">
<a name="zend.auth.adapter.ldap.server-options.table"></a><p class="title"><b>Table 3.2. Server Options</b></p>
<div class="table-contents"><table summary="Server Options" border="1">
<colgroup>
<col>
<col>
</colgroup>
<thead><tr>
<th>Name</th>
<th>Description</th>
</tr></thead>
<tbody>
<tr>
<td><span class="strong"><strong>host</strong></span></td>
<td>
                        The hostname of LDAP server that these options represent. This option is required.
                    </td>
</tr>
<tr>
<td><span class="strong"><strong>port</strong></span></td>
<td>
                        The port on which the LDAP server is listening. If <span class="strong"><strong>useSsl</strong></span> is
                        <code class="code">true</code>, the default <span class="strong"><strong>port</strong></span> value is 636. If
                        <span class="strong"><strong>useSsl</strong></span> is <code class="code">false</code>, the default
                        <span class="strong"><strong>port</strong></span> value is 389.
                    </td>
</tr>
<tr>
<td><span class="strong"><strong>useSsl</strong></span></td>
<td>
                        If <code class="code">true</code>, this value indicates that the LDAP client should use SSL / TLS encrypted
                        transport. A value of <code class="code">true</code> is strongly favored in production environments to
                        prevent passwords from be transmitted in clear text. The default value is <code class="code">false</code>,
                        as servers frequently require that a certificate be installed separately after installation.
                        This value also changes the default <span class="strong"><strong>port</strong></span> value (see
                        <span class="strong"><strong>port</strong></span> description above).
                    </td>
</tr>
<tr>
<td><span class="strong"><strong>username</strong></span></td>
<td>
                        The DN of the account used to perform account DN lookups. LDAP servers that require the
                        username to be in DN form when performing the "bind" require this option. Meaning, if
                        <span class="strong"><strong>bindRequiresDn</strong></span> is <code class="code">true</code>, this option is
                        required. This account does not need to be a privileged account - a account with read-only
                        access to objects under the <span class="strong"><strong>baseDn</strong></span> is all that is necessary
                        (and preferred based on the <span class="emphasis"><em>Principle of Least Privilege</em></span>).
                    </td>
</tr>
<tr>
<td><span class="strong"><strong>password</strong></span></td>
<td>
                        The password of the account used to perform account DN lookups. If this option is not supplied,
                        the LDAP client will attempt an "anonymous bind" when performing account DN lookups.
                    </td>
</tr>
<tr>
<td><span class="strong"><strong>bindRequiresDn</strong></span></td>
<td>
                        Some LDAP servers require that the username used to bind be in DN form like
                        <span class="emphasis"><em>CN=Alice Baker,OU=Sales,DC=foo,DC=net</em></span> (basically all servers
                        <span class="emphasis"><em>except</em></span> AD). If this option is <code class="code">true</code>, this instructs
                        <code class="code">Zend_Ldap</code> to automatically retrieve the DN corresponding to the username being
                        authenticated, if it is not already in DN form, and then re-bind with the proper DN. The
                        default value is <code class="code">false</code>. Currently only Microsoft Active Directory Server (ADS) is
                        known <span class="emphasis"><em>not</em></span> to require usernames to be in DN form when binding, and
                        therefore this option may be <code class="code">false</code> with AD (and it should be, as retrieving the DN
                        requires an extra round trip to the server). Otherwise, this option must be set to
                        <code class="code">true</code> (e.g. for OpenLDAP). This option also controls the default
                        <span class="strong"><strong>acountFilterFormat</strong></span> used when searching for accounts. See the
                        <span class="strong"><strong>accountFilterFormat</strong></span> option.
                    </td>
</tr>
<tr>
<td><span class="strong"><strong>baseDn</strong></span></td>
<td>
                        The DN under which all accounts being authenticated are located. This option is required. If
                        you are uncertain about the correct <span class="strong"><strong>baseDn</strong></span> value, it should
                        be sufficient to derive it from the user's DNS domain using <span class="emphasis"><em>DC=</em></span>
                        components. For example, if the user's principal name is <span class="emphasis"><em>alice@foo.net</em></span>, a
                        <span class="strong"><strong>baseDn</strong></span> of <span class="emphasis"><em>DC=foo,DC=net</em></span> should work. A
                        more precise location (e.g., <span class="emphasis"><em>OU=Sales,DC=foo,DC=net</em></span>) will be more
                        efficient, however.
                    </td>
</tr>
<tr>
<td><span class="strong"><strong>accountCanonicalForm</strong></span></td>
<td>
                        A value of 2, 3 or 4 indicating the form to which account names should be canonicalized after
                        successful authentication. Values are as follows: 2 for traditional username style names (e.g.,
                        <span class="emphasis"><em>alice</em></span>), 3 for backslash-style names (e.g., <span class="emphasis"><em>FOO\alice</em></span>)
                        or 4 for principal style usernames (e.g., <span class="emphasis"><em>alice@foo.net</em></span>). The default
                        value is 4 (e.g., <span class="emphasis"><em>alice@foo.net</em></span>). For example, with a value of 3, the
                        identity returned by <code class="code">Zend_Auth_Result::getIdentity()</code> (and
                        <code class="code">Zend_Auth::getIdentity()</code>, if <code class="code">Zend_Auth</code> was used) will always be
                        <span class="emphasis"><em>FOO\alice</em></span>, regardless of what form Alice supplied, whether it be
                        <span class="emphasis"><em>alice</em></span>, <span class="emphasis"><em>alice@foo.net</em></span>, <span class="emphasis"><em>FOO\alice</em></span>,
                        <span class="emphasis"><em>FoO\aLicE</em></span>, <span class="emphasis"><em>foo.net\alice</em></span>, etc. See the
                        <span class="emphasis"><em>Account Name Canonicalization</em></span> section in the <code class="code">Zend_Ldap</code>
                        documentation for details. Note that when using multiple sets of server options it is
                        recommended, but not required, that the same
                        <span class="strong"><strong>accountCanonicalForm</strong></span> be used with all server options so that
                        the resulting usernames are always canonicalized to the same form (e.g., if you canonicalize to
                        <span class="emphasis"><em>EXAMPLE\username</em></span> with an AD server but to
                        <span class="emphasis"><em>username@example.com</em></span> with an OpenLDAP server, that may be awkward for the
                        application's high-level logic).
                    </td>
</tr>
<tr>
<td><span class="strong"><strong>accountDomainName</strong></span></td>
<td>
                        The FQDN domain name for which the target LDAP server is an authority (e.g.,
                        <code class="code">example.com</code>). This option is used to canonicalize names so that the username
                        supplied by the user can be converted as necessary for binding. It is also used to determine if
                        the server is an authority for the supplied username (e.g., if
                        <span class="strong"><strong>accountDomainName</strong></span> is <span class="emphasis"><em>foo.net</em></span> and the
                        user supplies <span class="emphasis"><em>bob@bar.net</em></span>, the server will not be queried, and a failure
                        will result). This option is not required, but if it is not supplied, usernames in principal
                        name form (e.g., <span class="emphasis"><em>alice@foo.net</em></span>) are not supported. It is strongly
                        recommended that you supply this option, as there are many use-cases that require generating
                        the principal name form.
                    </td>
</tr>
<tr>
<td><span class="strong"><strong>accountDomainNameShort</strong></span></td>
<td>
                        The 'short' domain for which the target LDAP server is an authority (e.g.,
                        <span class="emphasis"><em>FOO</em></span>). Note that there is a 1:1 mapping between the
                        <span class="strong"><strong>accountDomainName</strong></span> and
                        <span class="strong"><strong>accountDomainNameShort</strong></span>. This option should be used to
                        specify the NetBIOS domain name for Windows networks but may also be used by non-AD servers
                        (e.g., for consistency when multiple sets of server options with the backslash style
                        <span class="strong"><strong>accountCanonicalForm</strong></span>). This option is not required but if it
                        is not supplied, usernames in backslash form (e.g., <span class="emphasis"><em>FOO\alice</em></span>) are not
                        supported.
                    </td>
</tr>
<tr>
<td><span class="strong"><strong>accountFilterFormat</strong></span></td>
<td>
                        The LDAP search filter used to search for accounts. This string is a
                        <a href="http://php.net/printf" target="_top"><code class="code">printf()</code></a>-style expression that must
                        contain one '<code class="code">%s</code>' to accomodate the username. The default value is
                        '<code class="code">(&amp;(objectClass=user)(sAMAccountName=%s))</code>', unless
                        <span class="strong"><strong>bindRequiresDn</strong></span> is set to <code class="code">true</code>, in which case
                        the default is '<code class="code">(&amp;(objectClass=posixAccount)(uid=%s))</code>'. For example, if for
                        some reason you wanted to use <code class="code">bindRequiresDn = true</code> with AD you would need to set
                        <code class="code">accountFilterFormat = '(&amp;(objectClass=user)(sAMAccountName=%s))</code>'.
                    </td>
</tr>
</tbody>
</table></div>
</div>
<p><br class="table-break">
        </p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
                If you enable <code class="code">useSsl = true</code> you may find that the LDAP client generates an error
                claiming that it cannot validate the server's certificate. Assuming the PHP LDAP extension is
                ultimately linked to the OpenLDAP client libraries, to resolve this issue you can set
                "<code class="code">TLS_REQCERT never</code>" in the OpenLDAP client <code class="code">ldap.conf</code> (and restart the web
                server) to indicate to the OpenLDAP client library that you trust the server. Alternatively if you are
                concerned that the server could be spoofed, you can export the LDAP server's root certificate and put
                it on the web server so that the OpenLDAP client can validate the server's identity.
            </p></td></tr>
</table></div>
</div>
<div class="sect2" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="zend.auth.adapter.ldap.debugging"></a>3.5.5. Collecting Debugging Messages</h3></div></div></div>
<p>
            <code class="code">Zend_Auth_Adapter_Ldap</code> collects debugging information within its <code class="code">authenticate()</code>
            method. This information is stored in the <code class="code">Zend_Auth_Result</code> object as messages. The array
            returned by <code class="code">Zend_Auth_Result::getMessages()</code> is described as follows:

            </p>
<div class="table">
<a name="zend.auth.adapter.ldap.debugging.table"></a><p class="title"><b>Table 3.3. Debugging Messages</b></p>
<div class="table-contents"><table summary="Debugging Messages" border="1">
<colgroup>
<col>
<col>
</colgroup>
<thead><tr>
<th>Messages Array Index</th>
<th>Description</th>
</tr></thead>
<tbody>
<tr>
<td>Index 0</td>
<td>
                        A generic, user-friendly message that is suitable for displaying to users (e.g., "Invalid
                        credentials"). If the authentication is successful, this string is empty.
                    </td>
</tr>
<tr>
<td>Index 1</td>
<td>
                        A more detailed error message that is not suitable to be displayed to users but should be
                        logged for the benefit of server operators. If the authentication is successful, this string is
                        empty.
                    </td>
</tr>
<tr>
<td>Indexes 2 and higher</td>
<td>
                        All log messages in order starting at index 2.
                    </td>
</tr>
</tbody>
</table></div>
</div>
<p><br class="table-break">

            In practice index 0 should be displayed to the user (e.g., using the FlashMessenger helper), index 1 should
            be logged and, if debugging information is being collected, indexes 2 and higher could be logged as well
            (although the final message always includes the string from index 1).
        </p>
</div>
<div class="sect2" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="zend.auth.adapter.ldap.options-common-server-specific"></a>3.5.6. Common Options for Specific Servers</h3></div></div></div>
<div class="sect3" lang="en">
<div class="titlepage"><div><div><h4 class="title">
<a name="zend.auth.adapter.ldap.options-common-server-specific.active-directory"></a>3.5.6.1. Options for Active Directory</h4></div></div></div>
<p>
                For ADS, the following options are noteworthy:

                </p>
<div class="table">
<a name="zend.auth.adapter.ldap.options-common-server-specific.active-directory.table"></a><p class="title"><b>Table 3.4. Options for Active Directory</b></p>
<div class="table-contents"><table summary="Options for Active Directory" border="1">
<colgroup>
<col>
<col>
</colgroup>
<thead><tr>
<th>Name</th>
<th>Additional Notes</th>
</tr></thead>
<tbody>
<tr>
<td><span class="strong"><strong>host</strong></span></td>
<td>
                            As with all servers, this option is required.
                        </td>
</tr>
<tr>
<td><span class="strong"><strong>useSsl</strong></span></td>
<td>
                            For the sake of security, this should be <code class="code">true</code> if the server has the necessary
                            certificate installed.
                        </td>
</tr>
<tr>
<td><span class="strong"><strong>baseDn</strong></span></td>
<td>
                            As with all servers, this option is required. By default AD places all user accounts under
                            the <span class="emphasis"><em>Users</em></span> container (e.g.,
                            <span class="emphasis"><em>CN=Users,DC=foo,DC=net</em></span>), but the default is not common in larger
                            organizations. Ask your AD administrator what the best DN for accounts for your application
                            would be.
                        </td>
</tr>
<tr>
<td><span class="strong"><strong>accountCanonicalForm</strong></span></td>
<td>
                            You almost certainly want this to be 3 for backslash style names (e.g.,
                            <span class="emphasis"><em>FOO\alice</em></span>), which are most familiar to Windows users. You should
                            <span class="emphasis"><em>not</em></span> use the unqualified form 2 (e.g., <span class="emphasis"><em>alice</em></span>), as
                            this may grant access to your application to users with the same username in other trusted
                            domains (e.g., <span class="emphasis"><em>BAR\alice</em></span> and <span class="emphasis"><em>FOO\alice</em></span> will be
                            treated as the same user). (See also note below.)
                        </td>
</tr>
<tr>
<td><span class="strong"><strong>accountDomainName</strong></span></td>
<td>
                            This is required with AD unless <span class="strong"><strong>accountCanonicalForm</strong></span> 2
                            is used, which, again, is discouraged.
                        </td>
</tr>
<tr>
<td><span class="strong"><strong>accountDomainNameShort</strong></span></td>
<td>
                            The NetBIOS name of the domain users are in and for which the AD server is an authority.
                            This is required if the backslash style
                            <span class="strong"><strong>accountCanonicalForm</strong></span> is used.
                        </td>
</tr>
</tbody>
</table></div>
</div>
<p><br class="table-break">
            </p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
                    Technically there should be no danger of accidental cross-domain authentication with the current
                    <code class="code">Zend_Auth_Adapter_Ldap</code> implementation, since server domains are explicitly checked,
                    but this may not be true of a future implementation that discovers the domain at runtime or if an
                    alternative adapter is used (e.g., Kerberos). In general, account name ambiguity is known to be the
                    source of security issues so always try to use qualified account names.
                </p></td></tr>
</table></div>
</div>
<div class="sect3" lang="en">
<div class="titlepage"><div><div><h4 class="title">
<a name="zend.auth.adapter.ldap.options-common-server-specific.openldap"></a>3.5.6.2. Options for OpenLDAP</h4></div></div></div>
<p>
                For OpenLDAP or a generic LDAP server using a typical posixAccount style schema, the following options
                are noteworthy:

                </p>
<div class="table">
<a name="zend.auth.adapter.ldap.options-common-server-specific.openldap.table"></a><p class="title"><b>Table 3.5. Options for OpenLDAP</b></p>
<div class="table-contents"><table summary="Options for OpenLDAP" border="1">
<colgroup>
<col>
<col>
</colgroup>
<thead><tr>
<th>Name</th>
<th>Additional Notes</th>
</tr></thead>
<tbody>
<tr>
<td><span class="strong"><strong>host</strong></span></td>
<td>
                            As with all servers, this option is required.
                        </td>
</tr>
<tr>
<td><span class="strong"><strong>useSsl</strong></span></td>
<td>
                            For the sake of security, this should be <code class="code">true</code> if the server has the necessary
                            certificate installed.
                        </td>
</tr>
<tr>
<td><span class="strong"><strong>username</strong></span></td>
<td>
                            Required and must be a DN, as OpenLDAP requires that usernames be in DN form when
                            performing a bind. Try to use an unprivileged account.
                        </td>
</tr>
<tr>
<td><span class="strong"><strong>password</strong></span></td>
<td>
                            The password corresponding to the username above, but this may be omitted if the LDAP
                            server permits an anonymous binding to query user accounts.
                        </td>
</tr>
<tr>
<td><span class="strong"><strong>bindRequiresDn</strong></span></td>
<td>
                            Required and must be <code class="code">true</code>, as OpenLDAP requires that usernames be in DN form
                            when performing a bind.
                        </td>
</tr>
<tr>
<td><span class="strong"><strong>baseDn</strong></span></td>
<td>
                            As with all servers, this option is required and indicates the DN under which all accounts
                            being authenticated are located.
                        </td>
</tr>
<tr>
<td><span class="strong"><strong>accountCanonicalForm</strong></span></td>
<td>
                            Optional but the default value is 4 (principal style names like
                            <span class="emphasis"><em>alice@foo.net</em></span>), which may not be ideal if your users are used to
                            backslash style names (e.g., <span class="emphasis"><em>FOO\alice</em></span>). For backslash style names use
                            value 3.
                        </td>
</tr>
<tr>
<td><span class="strong"><strong>accountDomainName</strong></span></td>
<td>
                            Required unless you're using <span class="strong"><strong>accountCanonicalForm</strong></span> 2,
                            which is not recommended.
                        </td>
</tr>
<tr>
<td><span class="strong"><strong>accountDomainNameShort</strong></span></td>
<td>
                            If AD is not also being used, this value is not required. Otherwise, if
                            <span class="strong"><strong>accountCanonicalForm</strong></span> 3 is used, this option is required
                            and should be a short name that corresponds adequately to the
                            <span class="strong"><strong>accountDomainName</strong></span> (e.g., if your
                            <span class="strong"><strong>accountDomainName</strong></span> is
                            <span class="strong"><strong>foo.net</strong></span>, a good
                            <span class="strong"><strong>accountDomainNameShort</strong></span> value might be
                            <span class="emphasis"><em>FOO</em></span>).
                        </td>
</tr>
</tbody>
</table></div>
</div>
<p><br class="table-break">

            </p>
</div>
</div>
</div>
<div class="navfooter"><table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left">
<a accesskey="p" href="zend.auth.adapter.http.html">Prev</a> </td>
<td width="20%" align="center"><a accesskey="u" href="zend.auth.html">Up</a></td>
<td width="40%" align="right"> <a accesskey="n" href="zend.auth.adapter.openid.html">Next</a>
</td>
</tr>
<tr>
<td width="40%" align="left" valign="top">3.4. HTTP Authentication Adapter </td>
<td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td>
<td width="40%" align="right" valign="top"> 3.6. Open ID Authentication</td>
</tr>
</table></div>
<div class="revinfo"></div>
</body>
</html>
